﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;

namespace Atomic.Common.Validators
{
    /// <summary>
    /// 实体输入字段属性验证，基于.NET 3.5以上框架
    /// </summary>
    public static class EntityValidator
    {
        /// <summary>
        /// 验证实体或实体部分属性字段值是否有效，验证失败，返回第一个失败的原因
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="propertyNames">要验证或忽略验证的属性名称集合，如果为null则验证实体所有属性</param>
        /// <param name="exclude">只有propertyNames不为null的时候有效。true：表示只验证propertyNames中的数据；false：表示不验证propertyNames中的属性。</param>
        /// <exception cref="System.NullReferenceException">obj 为 null</exception>
        /// <returns>验证结果</returns>
        public static ValidatedResult Validate(this object obj, ICollection<string> propertyNames = null, bool exclude = true)
        {
            if (obj == null)
            {
                throw new NullReferenceException("验证对象不能为null");
            }

            string errorMessage = string.Empty;
            ValidationContext context = new ValidationContext(obj, null, null);
            List<ValidationResult> results = new List<ValidationResult>();
            bool flag = Validator.TryValidateObject(obj, context, results, true);   //验证所有属性
            if (null == propertyNames)
            {
                //有未通过的验证属性
                if (!flag)
                {
                    errorMessage = results.FirstOrDefault().ErrorMessage;   //则返回第一个错误
                }
            }
            else
            {
                if (!flag)
                {
                    //排除属性
                    if (exclude)
                    {
                        //逐个排除不需要验证的属性
                        foreach (string item in propertyNames)
                        {
                            ValidationResult tmp = results.FirstOrDefault(m => m.MemberNames.FirstOrDefault() == item);
                            results.Remove(tmp);
                        }
                        if (results.Count > 0)
                        {
                            errorMessage = results.FirstOrDefault().ErrorMessage;
                        }
                    }
                    else
                    {
                        //逐个查询需要验证的属性是否有未通过的
                        foreach (ValidationResult item in results)
                        {
                            if (propertyNames.Where(m => m == item.MemberNames.FirstOrDefault())
                                .Count() > 0)
                            {
                                errorMessage = item.ErrorMessage;
                                break;
                            }
                        }
                    }
                }
            }
            return new ValidatedResult()
            {
                Success = string.IsNullOrEmpty(errorMessage),
                FailureMessage = errorMessage
            };
        }
    }
}
